# -*- coding: utf-8 -*-

from contextlib import closing
import time
import simplejson
import httplib
import urllib
import threading
import logging
import hashlib

import openerp
from openerp import http
from openerp.http import request

from openerp.api import Environment

from openerp.addons.wechat.enterprise import WxApi, WxApplication
from openerp.modules.registry import RegistryManager

SUPERUSER_ID = 1

_logger = logging.getLogger(__name__)


# 微信企业号获取access_token处理类
class WeixinEnterprise(WxApplication):
    _corp_xml_id = 'dftg_weixin.weixin_dftg_enterprise'
    _app_xml_id = None
    default_interval = 7200  # 每个小时刷新一次所有微信权限组的access_token
    enterprise_id = None
    is_initialized = False
    wxapi = None
    threaded_token = None
    access_token = None
    jsapi_ticket = None

    def __init__(self):
        if not self.is_initialized:
            self.init_app()

    def init_app(self):
        if not self._app_xml_id:
            raise Exception("微信应用类请定义_app_xml_id")
        db_name = request.session.db
        if not db_name:
            return
        self.is_initialized = True
        db = RegistryManager.get(db_name)
        ir_model_data = openerp.registry(db_name)['ir.model.data']
        with closing(db.cursor()) as cr:
            self.enterprise_id = ir_model_data.xmlid_to_res_id(cr, 1, self._corp_xml_id)
            wechat_enterprise_obj = openerp.registry(db_name)['wechat.enterprise']
            wechat_enterprise = wechat_enterprise_obj.browse(cr, openerp.SUPERUSER_ID, self.enterprise_id)
            self.CORP_ID = wechat_enterprise.corp_id.encode("ascii")
            app_row_id = ir_model_data.xmlid_to_res_id(cr, 1, self._app_xml_id)
            if not app_row_id:
                raise Exception('weixin application xmlid: %s not found', self._app_xml_id)
            wechat_application = openerp.registry(db_name)['wechat.application']
            application_id = wechat_application.search(cr, SUPERUSER_ID, [('id', '=', app_row_id)])
            if not application_id:
                raise Exception('weixin application id: %s not found', app_row_id)

            application = wechat_application.browse(cr, SUPERUSER_ID, app_row_id)
            self.app_row_id = app_row_id
            self.SECRET = application.secret
            self.SECRET_TOKEN = application.callback_token
            self.ENCODING_AES_KEY = application.callback_aeskey
            self.APP_ID = application.application_id
            self.CORP_ID = application.enterprise_id.corp_id.encode("ascii")
            self.wxapi = WxApi(self.CORP_ID, self.SECRET)

        self.threaded_token = threading.Thread(target=self.get_token, args=(db_name,))
        self.threaded_token.setDaemon(True)
        self.threaded_token.start()


    # 后台线程获取权限组的access_token
    def get_token(self, db_name):
        while True:
            registry = openerp.registry(db_name)
            try:
                #获取微信app的token
                expires_in = self.request_weixin(registry, app_id=self.APP_ID, secret=self.SECRET)
                time.sleep(expires_in)
            except Exception:
                _logger.exception("weixin get token loop error, sleep and retry")
                time.sleep(5)

    # 向微信服务器获取access_token
    def request_weixin(self, registry, app_id=None, secret=None, context=None):
        with Environment.manage():
            http_client = None
            expires_in = 600
            try:
                #data = {'grant_type': 'client_credential', 'corpid': self.CORP_ID, 'corpsecret': secret}
                params = urllib.urlencode({})

                headers = {"Content-type": "application/x-www-form-urlencoded",
                           "Accept": "text/plain"}
                http_client = httplib.HTTPSConnection("qyapi.weixin.qq.com", timeout=5)
                http_client.request("GET", "/cgi-bin/gettoken?corpid=%s&corpsecret=%s" % (self.CORP_ID, secret), params, headers)

                response = http_client.getresponse()

                if response.status != 200:
                    _logger.error('weixin gettoken error, http status: %s', response.status)
                else:
                    data_string = response.read()
                    _logger.info('app %s get access_token: %s' % (app_id, data_string))
                    # {"access_token":"ACCESS_TOKEN","expires_in":7200}
                    return_data = simplejson.loads(data_string)
                    if return_data.get('errcode'):
                        _logger.error('corpid:%s, corpsecret:%s, get weixin access_token error: %s',
                                      self.CORP_ID, secret, data_string)
                    else:
                        access_token = return_data['access_token']
                        expires_in = return_data['expires_in']
                        timestamp = int(time.time())

                        res = {
                            'access_token': access_token,
                            'access_token_timestamp': timestamp,
                        }
                        self.access_token = access_token

                        #data.update({'access_token': access_token})
                        params = urllib.urlencode({})
                        http_client.request("POST", "/cgi-bin/get_jsapi_ticket?access_token=" + access_token, params, headers)
                        response = http_client.getresponse()
                        jsapi_ticket = None
                        if response.status != 200:
                            _logger.error('weixin get_jsapi_ticket error, http status: %s', response.status)
                        else:
                            data_string = response.read()
                            return_data = simplejson.loads(data_string)
                            if return_data.get('errmsg') != 'ok':
                                _logger.error('get_jsapi_ticket error: %s', data_string)
                            else:
                                jsapi_ticket = return_data['ticket']
                                res.update({
                                    'jsapi_ticket': jsapi_ticket,
                                    'jsapi_ticket_timestamp': timestamp
                                })
                                self.jsapi_ticket = jsapi_ticket
                        apo_obj = registry['wechat.application']
                        with closing(registry.cursor()) as cr:
                            apo_obj.write(cr, openerp.SUPERUSER_ID, self.app_row_id, res)

                            cr.commit()

            finally:
                if http_client:
                    http_client.close()
            return expires_in

    def get_jsapi_signature(self, cr, user_id, pool, context):
        kw = {}
        # session的uid不存在的时候？
        if user_id:
            kw.update({'user_id': user_id})
        elif request.session.uid:
            kw.update({'user_id': request.session.uid})

        jsapi_ticket = self.jsapi_ticket
        timestamp = int(time.time())
        nonce_str = 'Wm3WZYTPz0wzccnW'  # 随机字符串, 没有意义
        url = request.httprequest.url

        string1 = "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s" % (jsapi_ticket, nonce_str, timestamp, url)
        signature = hashlib.sha1(string1).hexdigest()
        # import ipdb
        # ipdb.set_trace()

        kw.update({
            'corp_id': self.CORP_ID,
            'timestamp': timestamp,
            'nonceStr': nonce_str,
            'signature': signature,
        })
        return kw